package com.example.listenmailforfsbot.util;

import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;

import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.MimeMultipart;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: dftdla
 */
public class ListenMail {

    public static final Boolean OPEN_START = false;
    public static final Boolean OPEN_STOP = true;
    private static final Properties PROPS = System.getProperties();
    private static Boolean OPEN = false;
    private static IMAPFolder folder;
    private static IMAPStore store;
    private static final Pattern pattern = Pattern.compile("\\w+@\\w+\\.\\w+");

    static {
        PROPS.setProperty("mail.imap.auth", "true");
        PROPS.setProperty("mail.store.protocol", "imap");
        PROPS.setProperty("mail.imap.ssl.enable", "true");
        PROPS.setProperty("mail.imap.auth.login.disable", "true");
        PROPS.setProperty("mail.imap.usesocketchannels", "true");
    }

    private String host;
    private Integer port;
    private String usermail;
    private String password;
    private String protocol;
    private String folderName;
    private String filterTitle;
    private Boolean skip;
    private Integer messageLastSize = null;
    @Resource
    private SendFeiShuBot sendFeiShuBot;
    @Resource
    private TextFilter textFilter;

    public ListenMail(String host, String protocol, Integer port, String usermail, String password, String folderName, String filterTitle, Boolean skip) {
        this.host = host;
        this.port = port;
        this.usermail = usermail;
        this.password = password;
        this.protocol = protocol;
        this.folderName = folderName;
        this.filterTitle = filterTitle;
        this.skip = skip;
    }

    public static void stop() {
        try {
            folder.close();
            store.close();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

    public Boolean setOpen(Boolean set) {
        OPEN = set;
        return true;
    }

    public Boolean getOpen() {
        return OPEN;
    }

    public Boolean startListen() {
        return setOpen(OPEN_START);
    }

    public Boolean stopListen() {
        return setOpen(OPEN_STOP);
    }

    private void openStore() throws Exception {
        Session session = Session.getInstance(PROPS, null);
        System.out.println("获取到Session,Time:\n\t\t" + LocalDateTime.now());
        // 2、通过session得到Store对象
        store = (IMAPStore) session.getStore(protocol);
        System.out.println("获取到store,Time:\n\t\t" + LocalDateTime.now());
        // 3、连上邮件服务器
        store.connect(host, port, usermail, password);
        System.out.println("已与imap建立连接,Time:\n\t\t" + LocalDateTime.now());
    }

    private void openFolder() {

        try {
            openStore();

            folder = (IMAPFolder) store.getFolder(folderName);

            if (folder == null) {
                throw new Exception("No IMAP INBOX");
            }

            System.out.println("folder启动,Time:\n\t\t" + LocalDateTime.now());
            folder.open(Folder.HOLDS_FOLDERS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void fetchMail() {

        if (OPEN) {
            System.out.println("邮件转发已被关闭");
            return;
        }

        try {
            openFolder();

            int size = folder.getMessageCount();

            System.out.println("从folder获得邮件数,Time:\n\t\t" + LocalDateTime.now());

            int unreadMessageCount = folder.getUnreadMessageCount();

            System.out.println("从folder获得未读邮件数,Time:\n\t\t" + LocalDateTime.now());

            System.out.println("邮件个数：" + size);

            if (unreadMessageCount == 0
                    || skip != null && skip && messageLastSize != null && messageLastSize == size) {

                System.out.println("跳过未读邮件检测,未读邮件数量:" + unreadMessageCount);

            } else {

                messageLastSize = size;

                for (int i = 0; i < size && unreadMessageCount >0 ; i++) {

                    ExecutorService executor = Executors.newSingleThreadExecutor();

                    int finalI = i;

                    Future<Message> future = executor.submit(()->folder.getMessage(size - finalI));

                    long time = System.currentTimeMillis();

                    Message message;
                    String subject;

                    try {

                        message = future.get(1000,TimeUnit.MILLISECONDS);
                        subject = message.getSubject();
                        System.out.println("获取邮件数据用时：" + (System.currentTimeMillis() - time) + "ms");

                    } catch (ExecutionException | InterruptedException | TimeoutException e) {

                        future.cancel(true);
                        executor.shutdown();
                        System.out.println("获取邮件数据超时,跳过本次定时任务");
                        break;

                    }

                    //判断主题包含WGCLOUD
                    if (!subject.contains(filterTitle)) {
                        System.out.println("邮件主题长度:" + subject.length());
                        continue;
                    }

                    if (message.getFlags().contains(Flags.Flag.SEEN)) {
                        System.out.println("邮件已读");
                        continue;
                    }

                    System.out.println("还剩" + (unreadMessageCount + 1) + "封未读邮件,未读邮件为:");
                    String from = message.getFrom()[0].toString();
                    Date date = message.getSentDate();
                    Matcher matcher = pattern.matcher(from);

                    System.out.println("\tFrom: \t\t" + (matcher.find()?matcher.group():from));
                    System.out.println("\tSubject: \t" + subject);
                    System.out.println("\tDate: \t\t" + date);
                    MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();

                    StringBuilder text = new StringBuilder();

                    // 遍历部件列表
                    for (int j = 0; j < mimeMultipart.getCount(); j++) {
                        BodyPart bodyPart = mimeMultipart.getBodyPart(j);

                        // 检查部件的内容类型
                        if (bodyPart.isMimeType("text/plain")) {
                            text.append((String) bodyPart.getContent());
                        } else if (bodyPart.isMimeType("text/html")) {
                            text.append((String) bodyPart.getContent());
                        }

                    }
                    unreadMessageCount--;
                    System.out.println(sendFeiShuBot.sendMessageToBot(textFilter.checkText(text.toString())));
                }
            }

        } catch (MessagingException | IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("接收完毕！");
        }
    }

    @Override
    public String toString() {
        return "ListenMail{" + "\n" +
                "\thost = '" + host + '\'' + "\n" +
                "\tport = " + port + "\n" +
                "\tusermail = '" + usermail + '\'' + "\n" +
                "\tpassword.length = " + password.length() + "\n" +
                "\tprotocol = '" + protocol + '\'' + "\n" +
                "\tfolderName = '" + folderName + '\'' + "\n" +
                "\tfilterTitle = '" + filterTitle + '\'' + "\n" +
                "\tskip = " + skip + "\n" +
                "\tmessageLastSize = " + messageLastSize + "\n" +
                "\tsendFeiShuBot = " + sendFeiShuBot + "\n" +
                "\ttextFilter = " + textFilter + "\n" +
                '}';
    }

    public Boolean checkPassword(String password) {
        return password.equals(this.password);
    }

    public Boolean checkWebHook(String url) {
        return sendFeiShuBot.checkHost(url);
    }

}

